#ifndef __PRT_LOG_H__
#define __PRT_LOG_H__

#include <stdio.h>
#include <time.h>

#ifdef __cplusplus
extern "C" {
#endif

/* 日志级别 */
#define LOG_LEVEL_NONE      0
#define LOG_LEVEL_ERRO      1
#define LOG_LEVEL_WARN      2
#define LOG_LEVEL_NOTE      3
#define LOG_LEVEL_INFO      4
#define LOG_LEVEL_DBUG      5

/* 默认日志级别 */
#ifndef LOG_LEVEL
#define LOG_LEVEL           LOG_LEVEL_ERRO
#endif

/* ANSI 终端颜色编码 */
#define COLOR_RED           "\033[31m"
#define COLOR_GREEN         "\033[32m"
#define COLOR_YELLOW        "\033[33m"
#define COLOR_BLUE          "\033[34m"
#define COLOR_MAGENTA       "\033[35m"
#define COLOR_CYAN          "\033[36m"
#define COLOR_DEFAULT       "\033[0m"

/* 打印带有时间戳的信息到指定的文件流 */
static inline void fprintf_timestamp(FILE *fp) {
    if (!fp)
        fp = stdout;

    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    fprintf(fp, COLOR_CYAN "[%5lld.%06lld] " COLOR_DEFAULT, 
            (long long)ts.tv_sec,                   /* 秒 */
            (long long)(ts.tv_nsec / 1000));        /* 微秒 */
}

/* 打印宏 */
#define prtt_log(fp, fmt, ...) do {                 \
    fprintf_timestamp(fp);                          \
    fprintf(fp, fmt COLOR_DEFAULT, ##__VA_ARGS__);  \
} while(0)

#define prt_log(fp, fmt, ...) do {                  \
    fprintf(fp, fmt COLOR_DEFAULT, ##__VA_ARGS__);  \
} while(0)

#if LOG_LEVEL >= LOG_LEVEL_ERRO
#define prt_erro(fmt, ...)  \
    prt_log(stderr, COLOR_RED fmt, ##__VA_ARGS__)
#define prtt_erro(fmt, ...) \
    prtt_log(stderr, COLOR_RED fmt, ##__VA_ARGS__)
#else
#define prt_erro(fmt, ...)
#define prtt_erro(fmt, ...)
#endif

#if LOG_LEVEL >= LOG_LEVEL_WARN
#define prt_warn(fmt, ...)  \
    prt_log(stdout, COLOR_YELLOW fmt, ##__VA_ARGS__)
#define prtt_warn(fmt, ...) \
    prtt_log(stdout, COLOR_YELLOW fmt, ##__VA_ARGS__)
#else
#define prt_warn(fmt, ...)
#define prtt_warn(fmt, ...)
#endif

#if LOG_LEVEL >= LOG_LEVEL_NOTE
#define prt_note(fmt, ...)  \
    prt_log(stdout, COLOR_CYAN fmt, ##__VA_ARGS__)
#define prtt_note(fmt, ...) \
    prtt_log(stdout, COLOR_CYAN fmt, ##__VA_ARGS__)
#else
#define prt_note(fmt, ...)
#define prtt_note(fmt, ...)
#endif

#if LOG_LEVEL >= LOG_LEVEL_INFO
#define prt_info(fmt, ...)  \
    prt_log(stdout, COLOR_GREEN fmt, ##__VA_ARGS__)
#define prtt_info(fmt, ...) \
    prtt_log(stdout, COLOR_GREEN fmt, ##__VA_ARGS__)
#else
#define prt_info(fmt, ...)
#define prtt_info(fmt, ...)
#endif

#ifdef DEBUG
#if LOG_LEVEL >= LOG_LEVEL_DBUG
#define prt_dbug(fmt, ...)  \
    prt_log(stdout, COLOR_DEFAULT fmt, ##__VA_ARGS__)
#define prtt_dbug(fmt, ...) \
    prtt_log(stdout, COLOR_DEFAULT fmt, ##__VA_ARGS__)
#else
#define prt_dbug(fmt, ...)
#define prtt_dbug(fmt, ...)
#endif
#else /* DEBUG */
#define prt_dbug(fmt, ...)
#define prtt_dbug(fmt, ...)
#endif /* DEBUG */

#ifdef __cplusplus
}
#endif
#endif /* __PRT_LOG_H__ */
